#ifndef __SYLAR_FIBER_H__
#define __SYLAR_FIBER_H__

#include <ucontext.h>
#include <memory>
#include <functional>
#include "thread.h"

namespace sylar{
/**
 * @brief 协程实现
 */
class Fiber : public std::enable_shared_from_this<Fiber>{
friend class Scheduler;
public:
    typedef std::shared_ptr<Fiber> ptr;
    //协程状态
    enum State{
        INIT,  
        HOLD,  
        EXEC,
        TERM,
        READY,
        EXCEPT
    };
private:
    Fiber();    //禁用默认构造函数
public:
    Fiber(std::function<void()> cb, size_t stacksize = 0, bool use_caller = false);
    ~Fiber();
    // 重置协程函数, 同时重置状态
    void reset(std::function<void()> cb);
    //切换当前协程执行
    void swapIn();
    //切换当前协程到后台
    void swapOut();

    void call();

    void back();

    uint64_t getId() {return m_id;}

    State getState() const { return m_state;}
public:
    //设置当前协程
    static void SetThis(Fiber *f);
    //返回当前协程
    static Fiber::ptr GetThis();
    //协程切换到后台, 并设置Ready状态
    static void YieldToReady();
    //协程切换到后台, 并设置Hold状态
    static void YieldToHold();
    //总协程数
    static uint64_t TotalFibers();

    static void MainFunc();

    static void CallerMainFunc();
    
    static uint64_t GetFiberId();
private:
    uint64_t m_id = 0;  //协程id    
    uint32_t m_stacksize = 0;   //协程栈大小
    State m_state = INIT;   //协程状态

    ucontext_t m_ctx;       //协程上下文信息
    void* m_stack = nullptr;    //协程栈空间

    std::function<void()> m_cb; //协程的执行函数
};

}

#endif
